import { isObject } from "../../../utils";
import { hasOwn } from "../../../utils/shared";
import Dep from "./dep";
export function observeProxy(value) {
  const dep = new Dep()
  return new Proxy(value, {
    get: function (target, propKey, receiver) {
      // console.log(`getting ${propKey}!`);
      Dep.target && dep.depend();
      return Reflect.get(target, propKey, receiver);
    },
    set: function (target, propKey, value, receiver) {
      // console.log(`setting ${propKey}!`);
      dep.notify()
      return Reflect.set(target, propKey, value, receiver);
    }
  });
}
export function observe(value) {
  if (!isObject(value)) return;
  // 创建Observer实例：一个对象，一个Observer实例
  let ob;
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
    // 如果已经是响应式数据直接返回
    ob = value.__ob__
  } else {
    new Observer(value);
  }
  return ob;
}

// 作用：处理两种不同类型
class Observer {
  constructor(value) {
    // 判断value是obj还是数组
    if (isObject(value)) {
      this.walk(value)
    }
  }
  walk(value) {
    Object.keys(value).forEach(key => {
      defineReactive(value, key, value[key])
    });
    
  }
}
export function set(obj, key, val) {
  defineReactive(obj, key, val);
}
// 数据响应式
// 缺点：obj,key,val,dep都是闭包数据，在内存中占用
function defineReactive(obj, key, val) {
  // 特殊情况：val可能是对象，需要递归处理
  // const obj = {
  //   foo: 'foo',
  //   bar: 'bar',
  //   baz: { a: 1 }   val是对象
  // }
  // observe(val) // 创建Observer实例：一个对象，一个Observer实例
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      // console.log('get', key);
      // 依赖收集: 把watcher和dep关联
      // 希望Watcher实例化时，访问一下对应key，同时把这个实例设置到Dep.target上面
      // console.log('get的Dep: ', Dep.target);
      Dep.target && dep.depend();
      return val
    },
    set(newVal) {
      if (newVal !== val) {
        // console.log('set', key, newVal);
        // 特殊情况：赋值一个对象
        // 例：obj.baz = { a: 100 };
        // observe(newVal)
        val = newVal
        // 通知更新
        dep.notify()
      }
    },
  })
}
